Session
一般称为会话控制,简单来说就是一种客户与网站/服务器更为安全的对话方式。一旦开启了session
会话,便可以在网站的任何页面使用或保持这个会话,从而让访问者与网站之间建立一种”对话”机制。
关于php session
php session
可以看做是一个特殊的变量,且该变量是用于存储关于用户会话的信息,或者更改用户会话的设置,需要注意的是,php session
变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的,且对应的具体session
值会存储于服务器端,这也是cookie
的主要区别,所以session
的安全性相对较高。
php session的工作流程
当开始一个会话时,PHP会尝试从请求中查找会话ID
(通常通过会话cookie
),如果发现请求的Cookies
、GET
、POST
中不存在session id
,PHP就会自动调用php_session_creat_id
函数创建一个新的会话,并且在http response
中通过set-cookie
头部发送给客户端保存。
有时候浏览器用户设置会禁止cookie
,当在客户端cookie
被禁用的情况下,php也可以自动将session id
添加到url参数中以及form的hidden字段中,但这需要将php.ini中的session.use_trans_sid
设为开启,也可以在运行时调用ini_set
来设置这个配置项。
会话开始之后,php就会将会话中的数据设置到$_SESSION
变量中。
下列代码是在$_SESSION
变量中注册变量的例子:
1 |
|
当php脚本停止的时候,它会自动读取$_SESSION
中的内容,并将其序列化,然后发送给会话保存管理器来进行保存。
默认情况下,PHP使用内置的文件会话保存管理器来完成session
的保存,也可通过配置session.save_handler
来修改所要采用的会话保存管理器。对于文件会话保存管理器,会将会话数据保存到配置项session.save_path
所指定的位置。
整个过程为:
php session在php.ini中的配置
Ps: 看看就好
- session.gc_divisor
php session垃圾回收机制相关配置 - session.sid_bits_per_character
指定编码的会话id字符中的位数 - session.save_path=””
该配置主要设置session的存储路径
`session.save_handler=””
该配置主要设定用户自定义存储函数,如果想使用php内置session存储机制之外的可以使用这个函数。 - session.use_strict_mode
严格会话模式,严格会话模式不接受未初始化的会话id并重新生成会话id - session.use_cookies
指定是否在客户端用cookie来存放id,默认启用 - session.cookie_secure
指定是否仅通过安全连接发送cookie,默认关闭 - session.use_only_cookies
指定是否在客户端仅仅使用cookie来存放会话id - session.name
指定会话名以用做cookie的名字,只能以字符数字组成,默认为PHPSESSID - session.auto_start
指定会话模块是否在请求开始启动一个会话,默认值为0,不启动 - session.cookie_lifetime
指定了发送到浏览器的cookie的生命周期,单位为秒,值为0表示”直到关闭浏览器”。默认为0 - session.cookie_path
指定要设置会话cookie的路径,默认为/ - session.cookie_domain
指定要设置会话cookie的域名,默认为无,表示根据cookie规范产生cookie的主机名 - session.cookie_httponly
将cookie标记为只能通过http协议访问,即无法通过脚本语言(例如JavaScript)访问Cookie,此设置可以有效地帮助通过XSS攻击减少身份盗用 - session.serialize_handler
定义用来序列化/反序列化的处理器的名字,默认使用php
,还有其他引擎,且不同的引擎的对应的session的存储方式不相同。 - session.gc_probablity
该配置项与 session.gc_divisor 合起来用来管理 garbage collection,即垃圾回收进程启动的概率 - session.gc_divisor
该配置项与session.gc_probability合起来定义了在每个会话初始化时启动垃圾回收进程的概率 - session.gc_maxlifetime
指定过了多少秒之后数据就会被视为“垃圾”并被清除,垃圾搜集可能会在session启动的时候开始( 取决于session.gc_probability 和 session.gc_divisor) - session.referer_check
包含有用来检查每个HTTP Referer
的子串。如果客户端发送了Referer信息但是在其中并未找到该子串,则嵌入的会话 ID 会被标记为无效。默认为空字符串 - session.cache_limiter
指定会话页面所使用的缓冲控制方法(none/nocache/private/private_no_expire/public
)。默认为nocache
- session.cache_expire
以分钟数指定缓冲的会话页面的存活期,此设定对nocache缓冲控制方法无效。默认为 180 - session.use_trans_sid
指定是否启用透明 SID 支持。默认禁用 - session.sid_length
配置会话ID字符串的长度。 会话ID的长度可以在22到256之间。默认值为32。 - session.trans_sid_tags
指定启用透明sid支持时重写哪些HTML标签以包括会话ID - session.trans_sid_hosts
指定启用透明sid支持时重写的主机,以包括会话ID - session.sid_bits_per_character
配置编码的会话ID字符中的位数 - session.upload_progress.enabled
启用上传进度跟踪,并填充$ _SESSION
变量, 默认启用。 - session.upload_progress.cleanup
读取所有POST数据(即完成上传)后,立即清理进度信息,默认启用 - session.upload_progress.prefix
配置$ _SESSION
中用于上传进度键的前缀,默认为upload_progress_ - session.upload_progress.name
$ _SESSION
中用于存储进度信息的键的名称,默认为PHP_SESSION_UPLOAD_PROGRESS
- session.upload_progress.freq
定义应该多长时间更新一次上传进度信息 - session.upload_progress.min_freq
更新之间的最小延迟 - session.lazy_write
配置会话数据在更改时是否被重写,默认启用
php session的存储机制
php session的存储机制是由sess.serialize_handler
来定义引擎的,默认是以文件的方式存储,且存储的文件文件名是sess_<SESSIONID>
,文件的内容就是session值的序列化之后的内容。session.serialize_handler
定义的引擎有三种:
名称 | 存储格式 |
---|---|
php(默认) | 键名+竖线+经过serialize()函数序列化后的值 |
php_binary | 键名的长度对应的ASCII字符+键名+经过serialize()函数序列化后的值 |
php_serialize | 经过serialize()函数序列化后的数组 |
注:自 PHP 5.5.4 起可以使用 php_serialize
上述三种处理器中,php_serialize
在内部简单地直接使用 serialize/unserialize
函数,并且不会有php
和 php_binary
所具有的限制。 使用较旧的序列化处理器导致$_SESSION
的索引既不能是数字也不能包含特殊字符(|和!
) 。
可以在session_start()
时传入serialize_handler=php_serialize
参数来修改session存储方式
php引擎
session.serialize_handler=php
时,例如:
1 |
|
此时的session文件内容为:session_1|s:5:"test1";session_2|s:5:"test2";
php_binary引擎
session.serialize_handler=php_binary
时,例如:
1 |
|
此时的文件内容为:<0x09>session_1s:5:"test1";<0x09>session_2s:5:"test2";
其中<0x09>
为键名session_1
的长度的ascii字符。
php_serialize引擎
session.serialize_handler=php_binary
时,例如:
1 |
|
此时文件内容为:a:2:{s:9:"session_1";s:5:"test1";s:9:"session_2";s:5:"test2";}
此时内容就是数组$SESSION
序列化后的值
php session反序列化的问题
简单的说,php
引擎和php_serialize
引擎这两个引擎生成的序列化格式本身是没有问题的,但是如果这两个处理器混合起来用,就会造成危害。
一个例子
定义一个session.php文件,用于传入session值:
1 |
|
存在另一个class.php文件:
1 |
|
这两个文件的作用很清晰,session.php
文件的引擎是php_serialize
,class.php
文件的引擎是php
,session.php
文件的作用是传入可控的session
值,class.php
文件的作用是在反序列化开始前输出Who are you?
,反序列化结束的时候输出name
值。
这两个文件如果想要利用php session反序列化,我们要在session.php
文件传入|
+序列化格式的值
,然后再次访问class.php
文件的时候,就会在调用session值的时候,触发。
首先生成序列化字符串,利用 payload 如下
1 |
|
生成序列化内容为:O:4:"test":1:{s:4:"name";s:5:"admin";}
传入session.php中的值为:|O:4:"test":1:{s:4:"name";s:5:"admin";}
此时session文件中的内容为: a:1:{s:7:"session";s:39:"|O:4:"test":1:{s:4:"name";s:5:"admin";}
再次访问class.php